#ifndef BUFFER_H
#define BUFFER_H

#ifndef MAYBE_USE
#define MAYBE_USE  [[maybe_unused]] [[nodiscard]]
#define VOID_USE   [[maybe_unused]]
#define NO_RET     [[noreturn]]
#endif


#include <vector>
#include <string>
#include <algorithm>


class Buffer {
public:
    static constexpr size_t kCheapPrepend = 8;
    static constexpr size_t kInitialSize = 1024;

    explicit Buffer(const size_t initialSize = kInitialSize)
        : buffer_(kCheapPrepend + initialSize)
          , readerIndex_(kCheapPrepend)
          , writerIndex_(kCheapPrepend) {
    }

    MAYBE_USE size_t readableBytes() const { return writerIndex_ - readerIndex_;}

    MAYBE_USE size_t writableBytes() const { return buffer_.size() - writerIndex_;}

    MAYBE_USE size_t prependableBytes() const { return readerIndex_;}

    MAYBE_USE const char *peek() const { return begin() + readerIndex_;}

    // onMessage string <- Buffer
    void retrieve(const size_t len) {
        if (len < readableBytes()) {
            // 应用只读取了刻度缓冲区数据的一部分，就是len，还剩下readerIndex_ += len -> writerIndex_
            readerIndex_ += len;
        } else {
            retrieveAll();
        }
    }

    void retrieveAll() { readerIndex_ = writerIndex_ = kCheapPrepend;}

    // 把onMessage函数上报的Buffer数据，转成string类型的数据返回
    std::string retrieveAllAsString() {
        return retrieveAsString(readableBytes()); // 应用可读取数据的长度
    }

    std::string retrieveAsString(const size_t len) {
        std::string result(peek(), len);
        retrieve(len); // 上面一句把缓冲区中可读的数据，已经读取出来，这里肯定要对缓冲区进行复位操作
        return result;
    }

    // buffer_.size() - writerIndex_    len
    void ensureWriteableBytes(const size_t len) {
        if (writableBytes() < len) {
            makeSpace(len); // 扩容函数
        }
    }

    // 把[data, data+len]内存上的数据，添加到writable缓冲区当中
    void append(const char *data, const size_t len) {
        ensureWriteableBytes(len);
        std::copy_n(data, len, beginWrite());
        writerIndex_ += len;
    }

    MAYBE_USE  char *beginWrite() { return begin() + writerIndex_;}

    MAYBE_USE  const char *beginWrite() const { return begin() + writerIndex_;}

    ssize_t readFd(int fd, int *saveErrno);

    ssize_t writeFd(int fd, int *saveErrno) const;

private:
    // vector底层数组首元素的地址，也就是数组的起始地址
    char *begin() { return &*buffer_.begin(); }

    MAYBE_USE const char *begin() const { return &*buffer_.begin();}

    void makeSpace(const size_t len) {
        if (writableBytes() + prependableBytes() < len + kCheapPrepend) {
            buffer_.resize(writerIndex_ + len);
        } else {
            const size_t readable = readableBytes();
            std::copy(begin() + readerIndex_,
                      begin() + writerIndex_,
                      begin() + kCheapPrepend);
            readerIndex_ = kCheapPrepend;
            writerIndex_ = readerIndex_ + readable;
        }
    }

    std::vector<char> buffer_;
    size_t readerIndex_;
    size_t writerIndex_;
};

#endif
